package dt.inlee.common.util;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Field;
import java.net.URLDecoder;
import java.util.Date;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;

import org.apache.commons.io.FileUtils;
import org.apache.commons.io.output.ByteArrayOutputStream;

import dt.inlee.common.constant.CommonConstant;
import dt.inlee.common.tools.DateUtil;

/**
 * 
 * @功能：常用工具类
 * @作者：印鲜刚
 * @创建日期：2010-04-20
 * 
 */
public class BaseUtil {
	private static long mmsTransactionId;
	private static long smsMsgId;
	static {
		mmsTransactionId = System.currentTimeMillis() * 2;
		smsMsgId = System.currentTimeMillis() * 2;
	}

	/**
	 * 使用模型驱动的时候将模型驱动vo进行字符串解码
	 * 
	 * @param obj
	 *            待转码的vo
	 * @throws IllegalArgumentException
	 *             参数错误！参数不能为空。。。
	 * @throws IllegalAccessException
	 *             参数错误！
	 * @throws UnsupportedEncodingException
	 *             不支持的编码方式
	 */
	public static void decodeObject(Object obj)
			throws IllegalArgumentException, IllegalAccessException,
			UnsupportedEncodingException {
		if (BaseUtil.isEmpty(obj)) {
			return;
		}
		// 取得该对象里面所有定义的字段,并对每个字段进行转码
		for (Field field : obj.getClass().getDeclaredFields()) {
			// 将此对象的 accessible 标志设置为指示的布尔值。(即,当该字段为private时,也可以访问)
			field.setAccessible(true);
			// 回指定对象上此 Field 表示的字段的值。(即,取得传入对象中改字段的值)
			Object fieldObj = field.get(obj);
			if (!BaseUtil.isEmpty(fieldObj)) {
				// 只有在字段为String类型的时候才有中文乱码,因为如果是其他类型的话,在类型转换的时候就出错了
				if (field.getType() == String.class) {
					// 将指定对象变量上此 Field 对象表示的字段设置为指定的新值。(即,将传入的对象里面的这个字段设置为转码后的值)
					field.set(
							obj,
							!fieldObj.toString().trim().isEmpty() ? URLDecoder
									.decode(fieldObj.toString(),
											CommonConstant.UTF8) : null);
				}
			}
		}
	}

	/**
	 * 字符串解码
	 * 
	 * @param str
	 *            待转码的字符串
	 * @throws UnsupportedEncodingException
	 *             不支持的编码方式
	 */
	public static void decodeString(String str)
			throws UnsupportedEncodingException {
		str = URLDecoder.decode(str, CommonConstant.UTF8);
	}

	/**
	 * 将指定字符串的后4个字符替换成*
	 * 
	 * @param source
	 * @param len
	 * @return
	 */
	public static String replacementPartString(String source) {
		return BaseUtil.replacementPartString(source, 4, '*');
	}

	/**
	 * 将指定字符串的后Len个字符替换成*
	 * 
	 * @param source
	 * @param len
	 * @return
	 */
	public static String replacementPartString(String source, int len) {
		return BaseUtil.replacementPartString(source, len, '*');
	}

	/**
	 * 将指定字符串的后Len个字符替换成replaceStr
	 * 
	 * @param source
	 * @param len
	 * @param replaceStr
	 * @return
	 */
	public static String replacementPartString(String source, int len,
			char replaceStr) {
		if (BaseUtil.isEmpty(source))
			return "";
		else {
			if (source.length() < 4)
				return source;
			else {
				String dest = source.substring(0, source.length() - 4);
				for (int i = 0; i < len; i++) {
					dest += replaceStr;
				}
				return dest;
			}
		}

	}

	/**
	 * 将boolean类型转换成中文字符串
	 * 
	 * @param whether
	 *            -boolean类型
	 * @return
	 */
	public static String booleanToChineseString(boolean whether) {
		if (whether)
			return "是";
		else
			return "否";
	}

	/**
	 * 将boolean类型转换成中指定文字符串
	 * 
	 * @param whether
	 * @param trueString
	 * @param falseString
	 * @return
	 */
	public static String booleanToChineseString(boolean whether,
			String trueString, String falseString) {
		if (whether)
			return trueString;
		else
			return falseString;
	}

	/**
	 * 用于处理编号（应用与公文等）
	 * 
	 */
	public static String idCode(String profix, String type, String year,
			String seq, int len) {
		String idCode = profix + type + year;
		for (int i = seq.length(); i < len; i++) {
			seq = "0" + seq;
		}
		return idCode + seq;
	}

	/**
	 * 文件名生成（临时文件名、有效文件名生成方法一致）
	 * 
	 * 主要由三部分构成
	 * 
	 * 1、时间（hhmmssSSS）
	 * 
	 * 2、id号（如：用户ID、IP地址）
	 * 
	 * 3、流水号
	 * 
	 * @param String
	 *            id id号
	 * @param String
	 *            sequence 流水号
	 * @return String 文件名
	 */
	public static String composeFileName(String id, int sequence) {
		return DateUtil.shortTimeToString(new Date()) + "_" + id + "_"
				+ sequence;
	}

	/**
	 * 文件名生成（临时文件名、有效文件名生成方法一致）
	 * 
	 * 主要由两部分构成
	 * 
	 * 1、根目录
	 * 
	 * 2、时间（年份+月份+日期）
	 * 
	 * @param String
	 *            root根目录
	 * @return String 文件路径
	 */
	public static String composeFileFolder(String root) {
		String stringDate = DateUtil.shortDateToString(new Date());
		return root + "/" + stringDate.substring(0, 4) + "/"
				+ stringDate.substring(4, 6) + "/" + stringDate.substring(6, 8);
	}

	/**
	 * 文件名生成（临时文件名、有效文件名生成方法一致）
	 * 
	 * 主要由两部分构成
	 * 
	 * 2、时间（年份+月份+日期）
	 * 
	 * @param String
	 *            root根目录
	 * @return String 文件路径
	 */
	public static String composeFileFolder() {
		String stringDate = DateUtil.shortDateToString(new Date());
		return stringDate.substring(0, 4) + "/" + stringDate.substring(4, 6)
				+ "/" + stringDate.substring(6, 8);
	}

	/**
	 * base64编码
	 * 
	 * @param String
	 *            context 内容
	 * @return String 编码结果
	 * @throws UnsupportedEncodingException
	 */
	public static String base64EncodeEx(String context)
			throws UnsupportedEncodingException {
		String base64 = new sun.misc.BASE64Encoder().encode(context
				.getBytes("UTF-8"));
		return base64.replaceAll("[\\s+=]", "a");
	}

	public static String base64Decode(String context)
			throws UnsupportedEncodingException, IOException {
		return new String(new sun.misc.BASE64Decoder().decodeBuffer(context),
				"UTF-8");
	}

	public static InputStream openInputStream(String path) throws IOException {
		return FileUtils.openInputStream(new File(path));
	}

	/**
	 * 去空格
	 * 
	 * @param source
	 * @return
	 */
	public static String trim(String source) {
		if (BaseUtil.isEmpty(source))
			return "";
		else
			return source.trim();
	}

	public static String trimEx(String source) {
		if (BaseUtil.isEmpty(source))
			return "";
		source = source.trim();
		source = source.substring(source.lastIndexOf(" ") < 0 ? 0 : source
				.lastIndexOf(" "));
		return source;
	}

	public static boolean isMobile(String mobile) {
		Pattern pattern = Pattern.compile("(86)?[1]{1}[0-9]{10}");
		Matcher matcher = pattern.matcher(mobile);
		return matcher.matches();
	}

	public static void object2Xml(Object obj, OutputStream output)
			throws JAXBException {
		JAXBContext context = JAXBContext.newInstance(obj.getClass());
		Marshaller m = context.createMarshaller();
		m.marshal(obj, output);
	}

	public static String object2XmlSubString(Object obj, int offset, int offApp)
			throws JAXBException {
		ByteArrayOutputStream out = new ByteArrayOutputStream();
		object2Xml(obj, out);
		byte[] outByte = out.toByteArray();
		return new String(outByte, offset, outByte.length - offset - offApp);
	}

	public synchronized static String getTransactionId() {
		return Long.toString(mmsTransactionId++);
	}

	public synchronized static long getMsgId() {
		return smsMsgId++;
	}

	/**
	 * 判断Map<String,Object>里指定key的value值是否为空
	 * 
	 * @param params
	 * @param key
	 * @return boolean -true:表示value为空;false:表示value为非空
	 */
	public static boolean isEmpty(Map<String, Object> params, String key) {
		if (isEmpty(params))
			return true;
		else {
			if (params.containsKey(key) && !isEmpty(params.get(key)))
				return false;
			return true;
		}
	}

	/**
	 * 判断对象是否为空
	 * 
	 * @param obj
	 *            -参数对象
	 * @return boolean -true:表示对象为空;false:表示对象为非空
	 */
	public static boolean isEmpty(Object obj) {
		return obj == null || obj.toString().equalsIgnoreCase("null")
				|| obj.toString().length() == 0;
	}

	/**
	 * 
	 * @param obj
	 * @param oldCode
	 * @param newCode
	 * @throws IllegalArgumentException
	 * @throws IllegalAccessException
	 * @throws UnsupportedEncodingException
	 */
	public static void decodeObject(Object obj, String oldCode, String newCode)
			throws IllegalArgumentException, IllegalAccessException,
			UnsupportedEncodingException {
		if (BaseUtil.isEmpty(obj)) {
			return;
		}
		// 取得该对象里面所有定义的字段,并对每个字段进行转码
		for (Field field : obj.getClass().getDeclaredFields()) {
			// 将此对象的 accessible 标志设置为指示的布尔值。(即,当该字段为private时,也可以访问)
			field.setAccessible(true);
			// 回指定对象上此 Field 表示的字段的值。(即,取得传入对象中改字段的值)
			Object fieldObj = field.get(obj);
			if (!BaseUtil.isEmpty(fieldObj)) {
				// 只有在字段为String类型的时候才有中文乱码,因为如果是其他类型的话,在类型转换的时候就出错了
				if (field.getType() == String.class) {
					// 将指定对象变量上此 Field 对象表示的字段设置为指定的新值。(即,将传入的对象里面的这个字段设置为转码后的值)
					field.set(obj,
							!fieldObj.toString().trim().isEmpty() ? new String(
									fieldObj.toString().getBytes(oldCode),
									newCode) : null);
				}
			}
		}
	}
	
	/**
	 * 
	 * @方法名:  getNumber
	 * @功能说明: TODO(提取字符中的所有数字组成新串) 
	 * @作者: 研发部-鄢松涛
	 * @时间: 2014-6-3下午04:39:22
	 * @param str
	 * @return
	 */
	public static String getNumber(String str){
	    String regEx="[^0-9]";   
	    Pattern p = Pattern.compile(regEx);   
	    Matcher m = p.matcher(str); 
	    return m.replaceAll("").trim();
	}
}
